import { createSelectorQuery, createIntersectionObserver, getSystemInfoSync } from '@tarojs/taro'

/**
 * 将列表格式化为二维数组
 * @param {any[]} list 一维数组
 * @param {number} segmentNum  自定义分段的数量，默认10
 * @param	{Function} handleComplate  二维列表是否已经把全部数据加载完成的回调
 * @param	{Function} setInitList  存储初始化的二维数组
 * @param	{Function} setTwoDimensionList  存储真正使用的二维数组
 */
export const formatList = (
  list: any[] = [],
  segmentNum,
  handleComplate,
  setInitList,
  setTwoDimensionList
) => {
  let arr: any[] = [] // 一个维度承载的数据
  const _list: any[] = [] // 分割的结果

  list.forEach((item, index) => {
    arr.push(item)
    if ((index + 1) % segmentNum === 0) {
      // 当循环到外部指定数量时，将arr作为一个维度的数据塞入_list
      _list.push(arr)
      arr = []
    }
  })

  // 将分段不足segmentNum的剩余数据装入_list
  const restList = list.slice(_list.length * segmentNum)
  if (restList?.length) {
    _list.push(restList)
    _list.length <= 1 && handleComplate()
  }

  setInitList(_list)
  // 取第一个维度的数据
  setTwoDimensionList(_list.slice(0, 1))
}

export const setHeight = (
  list,
  wholePageIndex,
  listId,
  setPageHeight,
  scrollViewProps,
  screenNum,
  currentInstance,
  twoDimensionList,
  setTwoDimensionList,
  pageHeight,
  initList
) => {
  const query = createSelectorQuery()
  // 通过 select 方法取到对应的节点，然后通过 getBoundingClientRect 获取元素大小相对于视口的位置
  query.select(`#${listId} .wrap_${wholePageIndex}`).boundingClientRect()
  query.exec((res) => {
    console.log('--res--', res);
    if (list.length) {
      setPageHeight(res?.[0]?.height)
    }
  })
  // 可视区域的监听
  miniObserve(
    wholePageIndex,
    scrollViewProps,
    listId,
    screenNum,
    currentInstance,
    twoDimensionList,
    setTwoDimensionList,
    pageHeight,
    initList
  )
}

const miniObserve = (
  wholePageIndex,
  scrollViewProps,
  listId,
  screenNum,
  currentInstance,
  twoDimensionList,
  setTwoDimensionList,
  pageHeight,
  initList
) => {
  let windowHeight
  windowHeight = getSystemInformation()
  const scrollHeight = scrollViewProps?.style?.height || windowHeight
  // 第一个参数需要组件实例
  // 然后调 relativeToViewport 指定页面显示区域作为参照区域
  const observer = createIntersectionObserver(currentInstance.page).relativeToViewport({
    // 渲染的时候除了可视区域，还要上下两个部分，增加了范围，减少了白屏率
    top: screenNum * scrollHeight,
    bottom: screenNum * scrollHeight,
  })

  // 指定目标节点并开始监听相交状态变化情况
  observer.observe(`#${listId} .wrap_${wholePageIndex}`, (res) => {
    if (res?.intersectionRatio <= 0) {
      // 当前节点不在监控范围内,用该维度所占高度填充二维数组
      setTwoDimensionList((preList) => {
        const newList = [...preList]
        newList[wholePageIndex] = { height: pageHeight[wholePageIndex] }
        return newList
      })
    } else if (!twoDimensionList[wholePageIndex]?.length) {
      // 如果有相交区域，则将数据回填
      setTwoDimensionList((preList) => {
        const newList = [...preList]
        newList[wholePageIndex] = initList[wholePageIndex]
        return newList
      })
    }
  })
}

const getSystemInformation = () => {
  try {
    const info = getSystemInfoSync()
    return info.windowHeight
  } catch (error) {
    console.log(error)
  }
}
